﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using SUMO.MediaBrowser.Foundation;
using SUMO.MediaBrowser.Controls;
using SUMO.MediaBrowser.ViewModel;
using USTF.Media.MediaService;
using USTF.Media.MediaServiceConsumer;

namespace SUMO.MediaBrowser
{
    public partial class MainPage : UserControl
    {
        
        public MainPage()
        {
            InitializeComponent();
        }

        private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
        {
            //when tree item selected, load items to wrap-panel
            Tree.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(Tree_SelectedItemChanged);

            //detect when we need to allow user to save changes (and report on how many changes are waiting)
            PendingModifications.Current.ModifiedItems.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(ModifiedItems_CollectionChanged);

            //detect when a save operation is in progress
            PendingModifications.Current.PropertyChanged += (object pndSender, System.ComponentModel.PropertyChangedEventArgs pndE)
                =>
                        {
                            if (pndE.PropertyName.Equals("IsSaving", StringComparison.InvariantCultureIgnoreCase))
                            {
                                Dispatcher.BeginInvoke(() => //UI thread-safe
                                    {
                                        SetSaveChangesDescription(PendingModifications.Current.ModifiedItems.Count);
                                    });
                            }
                        };

            //detect when there are errors
            PendingModifications.Current.SaveFailures.CollectionChanged +=
                (object failSender, System.Collections.Specialized.NotifyCollectionChangedEventArgs failE)
                    =>
                {
                    Dispatcher.BeginInvoke(() => //UI thread-safe
                                    {
                                        StatusErrors.Visibility = (PendingModifications.Current.SaveFailures.Count > 0) ? Visibility.Visible : Visibility.Collapsed;
                                        switch (PendingModifications.Current.SaveFailures.Count)
                                        {
                                            case 0:
                                                StatusErrorDescription.Text = "no errors";
                                                break;
                                            case 1:
                                                StatusErrorDescription.Text = "1 save error [TODO: add dialog to requeue!]";
                                                break;
                                            default:
                                                StatusErrorDescription.Text = PendingModifications.Current.SaveFailures.Count + " save errors [TODO: add dialog to requeue!]";
                                                break;
                                        }
                                    });
                };

            //Show server-service connection details window
            //TODO: If this is app startup (or on app startup), load values from user config
            //      or instance storage.
            var loginWin = Controls.LoginWindow.Current;
            loginWin.ViewModel = OpsContext.Current;
            loginWin.Show();

        }


        void SetSaveChangesDescription(int uploadPendingCount)
        {
            BtnSave.Content =
                String.Format("Sav{2} Changes ({0} item{1} modified)",
                    uploadPendingCount.ToString(),
                    (uploadPendingCount > 1) ? "s" : String.Empty,
                    (PendingModifications.Current.IsSaving) ? "ing" : "e"
                );

            switch (uploadPendingCount)
	        {
                case 0:
                    StatusChangeCount.Text = "No pending changes";
                    break;
                case 1:
                    StatusChangeCount.Text = uploadPendingCount.ToString() + " pending change";
                    break;
                default:
                    StatusChangeCount.Text = uploadPendingCount.ToString() + " pending changes";
                    break;
            }
            

        }

        /// <summary>
        /// Occurs when the ModifiedItems collection for the PendingChanges app-singleton class instance changes
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ModifiedItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            //get sender
            //(it is a singleton, but we may as well code against the event instance since it's being passed in)
            var modificationHandler = (ObservableCollection<HierarchicalMediaItem>)sender;

            //find out how many modification-saves are pending
            int uploadPendingCount = modificationHandler.Count;

            //perform UI operations as a result of information collected
            Dispatcher.BeginInvoke(() => //UI thread-safe
                                    {
                                        //enable or disable the save button according to whether or not there are any modifications available to be saved
                                        BtnSave.IsEnabled = (uploadPendingCount > 0);
                                        //set save button description
                                        SetSaveChangesDescription(uploadPendingCount);
                                    });
        }

        void Tree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            var selectedNode = e.NewValue as MediaTreeViewItem;
            if (selectedNode != null)
            {
                if (!selectedNode.Carrier.ChildrenRetreivedFromDataSource)
                    selectedNode.Carrier.PopulateChildrenFromDataSource();
                Pane.DataContext = selectedNode.Carrier;
            }
        }

        
        private void Login_Click(object sender, RoutedEventArgs e)
        {
            Controls.LoginWindow.Current.Show();
        }
      
        private void About_Click(object sender, RoutedEventArgs e)
        {
            Controls.AboutWindow.Current.Show();
        }

        private void PersistToServer_Click(object sender, RoutedEventArgs e)
        {
            Controls.UploadWindow.Current.Show();
        }
		
		private void AddMediaItem_Click(object sender, RoutedEventArgs e)
        {
			//allow user to add media items to currently selected tree location
            OpenFileDialog localMediaFileChooser = new OpenFileDialog()
            {
                Multiselect = true
            };

            bool? localMediaFileDialogChoice = localMediaFileChooser.ShowDialog();
            
            if (localMediaFileDialogChoice != null && localMediaFileDialogChoice.Value)
            {
                //TODO: do this in a BackgroundWorker and display a progress dialog
                //      as it is opening local files and getting byte[] is pretty quick
                //      most of the time, so this task is relatively low priority.
                var fileData = localMediaFileChooser.Files.Select(fileInfo =>
                    {
                        var stream = fileInfo.OpenRead();
                        byte[] data = new byte[stream.Length];
                        stream.Read(data, 0, data.Length);

                        MediaItem item = new NewMediaItem();
                        item.Properties.Add(CommonFieldNames.FILENAME, fileInfo.Name);

                        //TODO: add parent id
                        HierarchicalMediaItem result = new HierarchicalMediaItem(item, data);
                        result.DataModified = true;
                        return result;
                    }).ToList();

                //add to current item
                //current item is either selected item or root
                var selectedItem = Tree.SelectedItem as MediaTreeViewItem;
                if (selectedItem == null && Tree.Items.Count > 0 && Tree.Items.First() is MediaTreeViewItem)
                    selectedItem = Tree.Items.First() as MediaTreeViewItem;
                fileData.ForEach(selectedItem.Carrier.ChildItems.Add);
            }
        }

        private void StatusErrors_Click(object sender, RoutedEventArgs e)
        {
            ///TODO: Show dialog explaining what the error was for each item
            ///         and offering to retry each one (add it to the queue again.
            ///         
            PendingModifications.Current.SaveFailures.ToList().ForEach(failure =>
                MessageBox.Show(failure.ErrorMessage));
            PendingModifications.Current.SaveFailures.ToList().ForEach(failure => PendingModifications.Current.ModifiedItems.Add(failure.ItemToSave));
            PendingModifications.Current.SaveFailures.Clear();
        }
    }
}
